package errors

import (
	"encoding/json"
	"fmt"
	"gpt-api/framework/codes"
)

// Error implements the error interface.
type Error struct {
	Code   codes.Code `json:"code"`
	Detail string     `json:"detail"`
	Status string     `json:"status"`
}

func (e *Error) Error() string {
	b, _ := json.Marshal(e)
	return string(b)
}

// New generates a custom error.
func New(msg string, code codes.Code) *Error {
	return &Error{
		Code:   code,
		Detail: msg,
		Status: msg,
	}
}

func Wrap(err error, code codes.Code, message string) *Error {
	er := Error{
		Code:   code,
		Status: "",
	}
	if err != nil {
		er.Detail = fmt.Sprintf("%v", err)
	} else {
		er.Detail = message
	}

	return &er
}

// Parse tries to parse a JSON string into an error. If that
// fails, it will set the given string as the error detail.
func Parse(err string) *Error {
	e := new(Error)
	errr := json.Unmarshal([]byte(err), e)
	if errr != nil {
		e.Detail = err
	}
	return e
}

// BadRequest generates a 400 error.
func BadRequest(lang string, err error) *Error {
	return &Error{
		Code:   codes.BadRequest,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.BadRequest),
	}
}

// Unauthorized generates a 401 error.
func Unauthorized(lang string, err error) *Error {
	return &Error{
		Code:   codes.Unauthorized,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.Unauthorized),
	}
}

// Forbidden generates a 403 error.
func Forbidden(lang string, err error) *Error {
	return &Error{
		Code:   codes.Forbidden,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.Forbidden),
	}
}

// NotFound generates a 404 error.
func NotFound(lang string, err error) *Error {
	return &Error{
		Code:   codes.NotFound,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.NotFound),
	}
}

// MethodNotAllowed generates a 405 error.
func MethodNotAllowed(lang string, err error) *Error {
	return &Error{
		Code:   codes.MethodNotAllowed,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.MethodNotAllowed),
	}
}

// Timeout generates a 408 error.
func Timeout(lang string, err error) *Error {
	return &Error{
		Code:   codes.RequestTimeout,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.RequestTimeout),
	}
}

// Conflict generates a 409 error.
func Conflict(lang string, err error) *Error {
	return &Error{
		Code:   codes.Conflict,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.Conflict),
	}
}

// InternalServerError generates a 500 error.
func InternalServerError(lang string, err error) *Error {
	return &Error{
		Code:   codes.InternalServerError,
		Detail: fmt.Sprintf("%v", err),
		//Status: codes.Text(lang, codes.InternalServerError),
	}
}
